import { Node, Edge, Point } from '@antv/x6';
import type { ProcessProps } from './index';

const domParser = new DOMParser();

/**
 * 根据节点元素及其绘图元素获取节点配置对象
 */
const getNodeConfig=(_bpmnNode:Element,_bpmnShape:Element):Node.Metadata=>{
  const data = {} as any;
  let width=50,height=50,x=0,y=0;

  // 描述文档元素<documentation/>
  const _documentation = _bpmnNode.querySelector('documentation');
  if(_documentation && _documentation.innerHTML.length>0){data.documentation = _documentation.innerHTML.trim();}
  // 发起人
  if(_bpmnNode.hasAttribute('flowable:initiator')){data.initiator = _bpmnNode.getAttribute('flowable:initiator');}
  // 是否异步
  if(_bpmnNode.hasAttribute('flowable:async')){data.async = _bpmnNode.getAttribute('flowable:async');}
  // 是否独占
  if(_bpmnNode.hasAttribute('flowable:exclusive')){data.exclusive = _bpmnNode.getAttribute('flowable:exclusive');}
  // 是否补偿
  if(_bpmnNode.hasAttribute('isForCompensation')){data.isForCompensation = _bpmnNode.getAttribute('isForCompensation');}
  // 分类
  if(_bpmnNode.hasAttribute('flowable:category')){data.category = _bpmnNode.getAttribute('flowable:category');}
  // 到期时间
  if(_bpmnNode.hasAttribute('flowable:dueDate')){data.dueDate = _bpmnNode.getAttribute('flowable:dueDate');}
  // 优先级
  if(_bpmnNode.hasAttribute('flowable:priority')){data.priority = _bpmnNode.getAttribute('flowable:priority');}
  // 跳过表达式
  if(_bpmnNode.hasAttribute('flowable:skipExpression')){data.skipExpression = _bpmnNode.getAttribute('flowable:skipExpression');}
  // 处理用户
  if(_bpmnNode.hasAttribute('flowable:assignee')){data.assignee = _bpmnNode.getAttribute('flowable:assignee');}
  // 候选用户
  if(_bpmnNode.hasAttribute('flowable:candidateUsers')){data.candidateUsers = _bpmnNode.getAttribute('flowable:candidateUsers');}
  // 候选用户组
  if(_bpmnNode.hasAttribute('flowable:candidateGroups')){data.candidateGroups = _bpmnNode.getAttribute('flowable:candidateGroups');}
  // 服务任务Java类
  if(_bpmnNode.hasAttribute('flowable:class')){data.class = _bpmnNode.getAttribute('flowable:class');}
  // 服务任务结果变量名
  if(_bpmnNode.hasAttribute('flowable:resultVariableName')){data.resultVariableName = _bpmnNode.getAttribute('flowable:resultVariableName');}
  // 服务任务可触发的
  if(_bpmnNode.hasAttribute('flowable:triggerable')){data.triggerable = _bpmnNode.getAttribute('flowable:triggerable');}
  // 服务任务结果变量局部有效
  if(_bpmnNode.hasAttribute('flowable:useLocalScopeForResultVariable')){data.useLocalScopeForResultVariable = _bpmnNode.getAttribute('flowable:useLocalScopeForResultVariable');}
  // 服务任务结果变量瞬态存储
  if(_bpmnNode.hasAttribute('flowable:storeResultVariableAsTransient')){data.storeResultVariableAsTransient = _bpmnNode.getAttribute('flowable:storeResultVariableAsTransient');}
  // 多实例元素<multiInstanceLoopCharacteristics/>
  const _multiInstance = _bpmnNode.querySelector('multiInstanceLoopCharacteristics');
  if(_multiInstance){
    data.multi_isSequential = _multiInstance.getAttribute("isSequential");
    // 集合
    if(_multiInstance.hasAttribute("flowable:collection")){data.multi_collection = _multiInstance.getAttribute("flowable:collection");}
    // 元素变量
    if(_multiInstance.hasAttribute("flowable:elementVariable")){data.multi_elementVariable = _multiInstance.getAttribute("flowable:elementVariable");}
    // 基数<loopCardinality/>
    const _loopCardinality = _bpmnNode.querySelector("loopCardinality");
    if(_loopCardinality && _loopCardinality.innerHTML.length>0){data.multi_loopCardinality = _loopCardinality.innerHTML.trim();}
    // 完成条件<completionCondition/>
    const _completionCondition = _bpmnNode.querySelector("completionCondition");
    if(_completionCondition && _completionCondition.innerHTML.length>0){data.multi_completionCondition = _completionCondition.innerHTML.trim();}
  }
  // 扩展元素<extensionElements/>
  const _extensionElements = _bpmnNode.querySelector("extensionElements");
  if(_extensionElements){
    // 动态表单属性元素<flowable:formProperty/>
    const _formProperties = _extensionElements.querySelectorAll('formProperty');
    if(_formProperties && _formProperties.length>0){
      data.formProperty = [] as any;
      _formProperties.forEach((_formProperty)=>{
        const formProperty = {
          id: _formProperty.getAttribute("id"),
          name: _formProperty.getAttribute("name"),
          type: _formProperty.getAttribute("type"),
          expression: _formProperty.getAttribute("expression"),
          variable: _formProperty.getAttribute("variable"),
          default: _formProperty.getAttribute("default")
        } as any;
        if(_formProperty.getAttribute("readable")==='false'){formProperty.readable='false';}
        if(_formProperty.getAttribute("writable")==='false'){formProperty.writable='false';}
        if(_formProperty.getAttribute("required")==='true'){formProperty.required='true';}
        data.formProperty.push(formProperty)
      });
    }
  }

  // 图形大小和位置
  if(_bpmnShape){
    const _bounds = _bpmnShape.querySelector('Bounds');
    if(_bounds){
      width = Number(_bounds.getAttribute('width'));
      height = Number(_bounds.getAttribute('height'));
      x = Number(_bounds.getAttribute('x'));
      y = Number(_bounds.getAttribute('y'));
    }
  }

  return {
    id: _bpmnNode.id,
    shape: _bpmnNode.getAttribute('xsi:shape') || 'shape',
    label: _bpmnNode.getAttribute('name') || '',
    data: data,
    width: width,
    height: height,
    position: {x: x, y: y}
  };
}

/**
 * 根据路径元素及其绘图元素获取LogicFlow路径配置对象
 */
const getEdgeConfig=(_bpmnFlow:Element,_bpmnEdge:Element):Edge.Metadata=>{
  const data = {} as any;
  const vertices:Point.PointLike[] = [];

  // 描述文档元素<documentation/>
  const _documentation = _bpmnFlow.querySelector('documentation');
  if(_documentation && _documentation.innerHTML.length>0){data.documentation = _documentation.innerHTML.trim();}
  // 跳过表达式
  if(_bpmnFlow.hasAttribute('skipExpression')){data.skipExpression = _bpmnFlow.getAttribute('skipExpression');}
  // 流转条件表达式元素<conditionExpression/>
  const _conditionExpression = _bpmnFlow.querySelector('conditionExpression');
  if(_conditionExpression && _conditionExpression.innerHTML.length>0){
    let value = _conditionExpression.innerHTML.trim().substring(9);
    value = value.substring(0,value.length-3);
    data.conditionExpression = value;
  }

  // 路径点
  if(_bpmnEdge){
    _bpmnEdge.querySelectorAll('waypoint').forEach((_waypoint)=>{
      vertices.push({
        x: Number(_waypoint.getAttribute('x')),
        y: Number(_waypoint.getAttribute('y')),
      });
    });
    vertices.shift();
    vertices.pop();
  }

  return {
    id: _bpmnFlow.id,
    shape: _bpmnFlow.getAttribute('xsi:shape') || 'shape',
    label: _bpmnFlow.getAttribute('name') || '',
    source: { cell: _bpmnFlow.getAttribute('sourceRef') as string },
    target: { cell: _bpmnFlow.getAttribute('targetRef') as string },
    data: data,
    vertices: vertices
  };
}

const convertGraph = (xml:string):{processProps:ProcessProps,nodes:Node.Metadata[],edges:Edge.Metadata[]}=>{
  const processProps:ProcessProps = {
    id: 'ID123456',
    name: '新建流程',
    isExecutable: true,
    candidateStarterUsers: '',
    candidateStarterGroups: '',
    documentation: '',
    isEagerExecutionFetching: 'false',
    formProperty: []
  }
  const nodes:Node.Metadata[] = [];
  const edges:Edge.Metadata[] = [];

  const _bpmnDoc = domParser.parseFromString(xml,'text/xml');
  console.log(xml);
  console.log(_bpmnDoc);

  const _process = _bpmnDoc.querySelector('definitions>process') as Element;
  processProps.id = _process.id;
  processProps.name = _process.getAttribute('name') || '';
  processProps.isExecutable = _process.getAttribute('isExecutable')==='true';
  processProps.candidateStarterUsers = _process.getAttribute('flowable:candidateStarterUsers') || '';
  processProps.candidateStarterGroups = _process.getAttribute('flowable:candidateStarterGroups') || '';
  processProps.documentation = _process.querySelector('documentation')?.innerHTML || '';

  const _formProperties = _process.querySelectorAll('startEvent>extensionElements>formProperty');
  _formProperties && _formProperties.forEach(_formProperty=>{
    processProps.formProperty.push({
      id: _formProperty.getAttribute("id") || '',
      name: _formProperty.getAttribute("name") || '',
      type: _formProperty.getAttribute("type") || 'string',
      expression: _formProperty.getAttribute("expression") || '',
      variable: _formProperty.getAttribute("variable") || '',
      default: _formProperty.getAttribute("default") || '',
      readable: _formProperty.getAttribute("readable") || 'true',
      writable: _formProperty.getAttribute("writable") || 'true',
      required: _formProperty.getAttribute("required") || 'false'
    });
  })

  const _bpmnNodes = _process.querySelectorAll('process>*:not(startEvent,sequenceFlow,documentation)');
  _bpmnNodes.forEach((_bpmnNode)=>{
    nodes.push(getNodeConfig(_bpmnNode,_bpmnDoc.querySelector(`definitions>*>*>BPMNShape[bpmnElement=${_bpmnNode.id}]`) as Element));
  })

  const _bpmnFlows = _process.querySelectorAll('sequenceFlow:not([id=START_FLOW])');
  _bpmnFlows.forEach((_bpmnFlow)=>{
    edges.push(getEdgeConfig(_bpmnFlow,_bpmnDoc.querySelector(`definitions>*>*>BPMNEdge[bpmnElement=${_bpmnFlow.id}]`) as Element));
  })

  console.log(processProps,nodes,edges);
  return {processProps,nodes,edges};
}

export default convertGraph;